package ca.badenhorst.ourtrition.activity;

import android.app.Activity;
import android.app.SearchManager;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import org.w3c.dom.Text;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import ca.badenhorst.ourtrition.R;
import ca.badenhorst.ourtrition.db.DatabaseHelper;
import ca.badenhorst.ourtrition.model.FoodDescription;
import ca.badenhorst.ourtrition.model.FoodGroup;

/**
 * Created by wade on 22/04/14.
 */
public class ListFoodsActivity extends Activity implements AdapterView.OnItemClickListener {

    private static final String ITEM = "(item)";

    private String foodGroupDesc;
    private String foodGroupCode;
    private ListView listView;
    private String query;
    private List<SubFood> subFoods;
    private String prepend;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_list_foods);

        listView = (ListView) findViewById(R.id.list_foods_list_view);
        listView.setAdapter(null);
        listView.setOnItemClickListener(this);

        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            foodGroupDesc = extras.getString(FoodGroup.DESCRIPTION);
            foodGroupCode = extras.getString(FoodGroup.GROUP_CODE);
        }

        Intent intent = getIntent();
        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
            query = intent.getStringExtra(SearchManager.QUERY);
        }

        if (TextUtils.isEmpty(query)) {
            setTitle(foodGroupDesc);
        } else {
            setTitle("search results for " + query);
        }

        new GetFoodListTask().execute();
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        String itemStr = (String) listView.getAdapter().getItem(position);
        itemStr = itemStr.replace(ITEM, "");

        for (SubFood sf : subFoods) {
            if (sf.getName().equals(itemStr)) {
                Intent foodDesc = new Intent(ListFoodsActivity.this, FoodDescriptionActivity.class);
                foodDesc.putExtra(FoodDescription.NDB_NO, sf.getNdbNo());
                startActivity(foodDesc);
                return;
            }
        }

        prepend = itemStr;
        refreshAdapter();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            // Respond to the action bar's Up/Home button
            case android.R.id.home:
                Intent upIntent = getParentActivityIntent();
                if (!TextUtils.isEmpty(prepend)) {
                    prepend="";
                    refreshAdapter();
                    //goBackOne();
                    return true;
                }

                // This activity is part of this app's task, so simply
                // navigate up to the logical parent activity.
                navigateUpTo(upIntent);
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void goBackOne() {
        String[] pieces = prepend.split(",");
        if (pieces.length == 1) {
            prepend = "";
        } else {
            prepend = constructNewPrepend(pieces, pieces.length - 1);
        }
        refreshAdapter();

    }

    private void refreshAdapter() {
        String[] items = getItems();
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, items);
        listView.setAdapter(adapter);
        listView.setTextFilterEnabled(true);
    }

    private String[] getItems() {
        return getItems(true);
    }

    private String[] getItems(boolean forward) {
        TreeSet<String> items = new TreeSet<String>();
        for (SubFood sf : subFoods) {
            String key = sf.getName();
            if (!prepend.equals("") && !key.startsWith(prepend)) { //all keys need to start with the prepend except for the root
                continue;
            }

            int index = -1;


            // Is this grabbing all root keys
            if (prepend.equals("")) {
                items.add(getRoot(key));
                continue;
            }

            // grab prepend plus next token
            String[] prepends = prepend.split(",");
            String[] keys = key.split(",");
            if (prepends.length == keys.length) {
                continue;
            }

            String category = constructNewPrepend(keys, prepends.length + 1);
            if (isFood(category) && hasSubGroups(category)) {
                items.add(category + ITEM);
                String temp = prepend;
                prepend = category;
                items.addAll(new TreeSet<String>(Arrays.asList(getItems())));
                prepend = temp;
            } else {
                items.add(category);
            }
        }

        if (items.size() == 1) {
            String category = items.first();
            if (!isFood(category) && hasSubGroups(category)) {
                prepend = category;
                return getItems();
            }
        }

        String[] itemArray = new String[items.size()];
        items.toArray(itemArray);

        return itemArray;
    }

    private class GetFoodListTask extends AsyncTask<Void, Void, Cursor> {

        public GetFoodListTask() {
        }

        @Override
        protected Cursor doInBackground(Void... voids) {
            DatabaseHelper helper = new DatabaseHelper(ListFoodsActivity.this);
            SQLiteDatabase db = helper.getReadableDatabase();

            StringBuffer buf = new StringBuffer("select id as _id, ndb_no, name from foods ");
            List<String> args = new ArrayList<String>();
            if (!TextUtils.isEmpty(foodGroupCode)) {
                buf.append("where food_group_cd=? ");
                args.add(foodGroupCode);
            }
            if (!TextUtils.isEmpty(query)) {
                String[] tokens = query.split(" "); // break on whitespace since not empty at least one item
                if (args.size() == 0) {
                    buf.append(" where name like ?");
                } else {
                    buf.append(" and name like ?");
                }
                args.add("%" + tokens[0] + "%");
                for (int i = 1; i < tokens.length; i++) {
                    buf.append(" and name like ?");
                    args.add("%" + tokens[i] + "%");
                }
            }

            prepend = "";

            String[] selectionArgs = new String[args.size()];
            args.toArray(selectionArgs);
            return db.rawQuery(buf.toString(), selectionArgs);
        }

        protected void onPostExecute(Cursor cursor) {
            subFoods = getSubFoods(cursor);
            refreshAdapter();
        }

        private List<SubFood> getSubFoods(Cursor cursor) {
            List<SubFood> subFs = new ArrayList<SubFood>();

            while (cursor.moveToNext()) {
                subFs.add(new SubFood(cursor.getString(1), cursor.getString(2)));
            }

            return subFs;
        }
    }

    private boolean hasSubGroups(String category) {
        for (SubFood sf : subFoods) {
            if (sf.getName().startsWith(category) && sf.getName().length() > category.length()) {
                return true;
            }
        }

        return false;

    }


    private String constructNewPrepend(String[] keys, int num) {
        StringBuffer buf = new StringBuffer(keys[0]);
        for (int i = 1; i < num; i++) {
            buf.append(",").append(keys[i]);
        }
        return buf.toString();
    }

    private String getRoot(String key) {
        int index = key.indexOf(",");
        if (index > 0) {
            return key.substring(0, index);
        } else {
            return key;
        }
    }

    private boolean isFood(String category) {
        for (SubFood sf : subFoods) {
            if (sf.getName().equals(category)) {
                return true;
            }
        }

        return false;
    }

    private class SubFood {
        String ndbNo;
        String name;

        private SubFood(String ndbNo, String name) {
            this.ndbNo = ndbNo;
            this.name = name;
        }

        public String getNdbNo() {
            return ndbNo;
        }

        public void setNdbNo(String ndbNo) {
            this.ndbNo = ndbNo;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}
